﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using LoungeRepo.Contracts.EntityStore;
using LoungeRepo.DispatcherEntityStore;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;

namespace Test.LoungeRepo.DispatcherEntityStore
{
    [TestFixture]
    public class testRegexDispatcherEntityStore
    {
        [Test]
        public void The_initial_default_entity_store_is_an_exception_entity_store()
        {
            var state = new RegexDispatcherEntityStore.State();

            new RegexDispatcherEntityStore(state);

            Assert.IsInstanceOfType(typeof(NullEntityStore), state.RegisteredEntityStores.Last().EntityStore);
        }
        

        [Test]
        public void Registers_default_entity_store()
        {
            var defaultEntityStore = MockRepository.GenerateStub<IEntityStore>();
            var state = new RegexDispatcherEntityStore.State();
            var sut = new RegexDispatcherEntityStore(state);

            sut.RegisterDefaultPartitionEntityStore(defaultEntityStore);

            Assert.AreSame(defaultEntityStore, state.RegisteredEntityStores.First().EntityStore);
        }


        [Test]
        public void Registers_entity_store()
        {
            var regexA = new Regex("A");
            var entityStoreA = MockRepository.GenerateStub<IEntityStore>();

            var state = new RegexDispatcherEntityStore.State();
            var sut = new RegexDispatcherEntityStore(state);

            sut.RegisterPartitionEntityStore(regexA, entityStoreA);

            Assert.AreSame(regexA, state.RegisteredEntityStores.First().PartitionNamePattern);
            Assert.AreSame(entityStoreA, state.RegisteredEntityStores.First().EntityStore);
        }


        [Test]
        public void Registers_entity_stores_in_the_order_specified()
        {
            var defaultEntityStore = MockRepository.GenerateStub<IEntityStore>();
            var entityStoreA = MockRepository.GenerateStub<IEntityStore>();
            var entityStoreB = MockRepository.GenerateStub<IEntityStore>();

            var state = new RegexDispatcherEntityStore.State();
            var sut = new RegexDispatcherEntityStore(state);

            sut.RegisterPartitionEntityStore(null, entityStoreA);
            sut.RegisterDefaultPartitionEntityStore(defaultEntityStore);
            sut.RegisterPartitionEntityStore(null, entityStoreB);

            Assert.That(state.RegisteredEntityStores.Select(r => r.EntityStore).ToArray(), 
                        Is.EqualTo(new[] {entityStoreA, entityStoreB, defaultEntityStore}));
        }

        [Test]
        public void Disposes_all_entity_stores()
        {
            var defaultEntityStore = MockRepository.GenerateMock<IEntityStore>();
            var entityStoreA = MockRepository.GenerateMock<IEntityStore>();

            using (var sut = new RegexDispatcherEntityStore())
            {
                sut.RegisterDefaultPartitionEntityStore(defaultEntityStore);
                sut.RegisterPartitionEntityStore(null, entityStoreA);
            }

            defaultEntityStore.AssertWasCalled(x => x.Dispose());
            entityStoreA.AssertWasCalled(x => x.Dispose());
        }


        [Test]
        public void Selects_entity_store_for_Store()
        {
            var defaultEntityStore = MockRepository.GenerateMock<IEntityStore>();
            var mockIStreamedEntity = MockRepository.GenerateMock<IStreamedEntity>();
            mockIStreamedEntity.Expect(x => x.Id).Return("42");
            mockIStreamedEntity.Expect(x => x.Partition).Return("Arthur Dent");

            var sut = new RegexDispatcherEntityStore();
            sut.RegisterDefaultPartitionEntityStore(defaultEntityStore);

            sut.Store(mockIStreamedEntity);

            defaultEntityStore.AssertWasCalled(x => x.Store(mockIStreamedEntity));
        }


        [Test]
        public void Selects_entity_store_for_Delete()
        {
            var defaultEntityStore = MockRepository.GenerateMock<IEntityStore>();

            var sut = new RegexDispatcherEntityStore();
            sut.RegisterDefaultPartitionEntityStore(defaultEntityStore);

            sut.Delete("42", "Arthur Dent");

            defaultEntityStore.AssertWasCalled(x => x.Delete("42", "Arthur Dent"));
        }

        
        [Test]
        public void Selects_entity_store_for_Load()
        {
            var defaultEntityStore = MockRepository.GenerateMock<IEntityStore>();
            var loadedStreamedEntity = MockRepository.GenerateStub<IStreamedEntity>();
            defaultEntityStore.Expect(x => x.Load("42", "Arthur Dent")).Return(loadedStreamedEntity);

            var sut = new RegexDispatcherEntityStore();
            sut.RegisterDefaultPartitionEntityStore(defaultEntityStore);

            var ret = sut.Load("42", "Arthur Dent");

            defaultEntityStore.AssertWasCalled(x => x.Load("42", "Arthur Dent"));
            Assert.AreEqual(ret, loadedStreamedEntity);
        }
    }
}
